using System;
using System.Collections.Generic;
using System.Data;

namespace Glpt.Data
{
    /// <summary>
    /// XML数据类
    /// </summary>
    public class XmlDataTable
    {
        private string Content = "";
        private string NodeName = "";
        private string NameType = "";
        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        /// <param name="file_name">内容</param>
        /// <param name="node_name">节点名</param>
        /// <param name="name_type">精简列名 0全部精简 1部分精简 2不精简</param>
        public XmlDataTable(string content, string node_name, string name_type)
        {
            Content = content;
            NodeName = node_name;
            NameType = name_type;
        }
        /// <summary>
        /// 转成数据表
        /// </summary>
        /// <returns>数据表</returns>
        public DataTable GetDataTable()
        {
            DataTable dt = new DataTable();
            string keyword2 = "";
            int ibegin = 0;
            string[] keys = NodeName.Split(new char[] { '>' }, StringSplitOptions.RemoveEmptyEntries);
            if (keys.Length == 0) throw new Exception("没有定义NodeName");
            for (int i = 0; i < keys.Length; i++)
            {
                keyword2 = "<" + keys[i] + ">";
                ibegin = Content.IndexOf(keyword2, ibegin);
                if (ibegin >= 0)
                {
                    if (i < keys.Length - 1)
                        ibegin += keyword2.Length;
                    else
                        NodeName = keys[i];
                }
                else
                    break;
            }
            while (ibegin >= 0)
            {
                ibegin += keyword2.Length;
                string keyword = "</" + NodeName + ">";
                int iend = Content.IndexOf(keyword, ibegin);
                if (iend > ibegin)
                {
                    string Content2 = Content.Substring(ibegin, iend - ibegin);
                    int idx2 = Content2.IndexOf(keyword2);
                    while (idx2 >= 0)
                    {
                        iend = Content.IndexOf(keyword, iend + 1);
                        if (iend > ibegin)
                            Content2 = Content.Substring(ibegin, iend - ibegin);
                        else
                            throw new Exception("格式错误");
                        idx2 = Content2.IndexOf(keyword2, idx2 + keyword2.Length);
                    }
                    Dictionary<string, string> dict = new Dictionary<string, string>();
                    XMLMatch(Content2, "", dict);
                    DataRow dr = dt.NewRow();
                    foreach (string key in dict.Keys)
                    {
                        if (!dt.Columns.Contains(key))
                            dt.Columns.Add(key);
                        dr[key] = dict[key];
                    }
                    dt.Rows.Add(dr);
                }
                ibegin = Content.IndexOf(keyword2, iend + keyword.Length);
            }

            foreach (DataColumn dc in dt.Columns)
            {
                int idx = dc.ColumnName.LastIndexOf('|');
                if (idx >= 0)
                {
                    string field_name = dc.ColumnName.Substring(idx + 1, dc.ColumnName.Length - idx - 1);
                    if (NameType.Equals("0"))
                    {
                        string new_field_name = field_name;
                        int icol = 1;
                        while (dt.Columns.Contains(new_field_name))
                        {
                            icol++;
                            new_field_name = field_name + icol.ToString();
                        }
                        dc.ColumnName = new_field_name;
                    }
                    else if (NameType.Equals("1"))
                    {
                        if (dt.Columns.Contains(field_name))
                            field_name = dc.ColumnName.Replace("|", "_");
                        if (!dt.Columns.Contains(field_name))
                            dc.ColumnName = field_name;
                    }
                    else
                    {
                        field_name = dc.ColumnName.Replace("|", "_");
                        if (!dt.Columns.Contains(field_name))
                            dc.ColumnName = field_name;
                    }
                }
            }
            return dt;
        }

        private void XMLMatch(string content, string node_name, Dictionary<string, string> dict)
        {
            int ibegin = content.IndexOf('<');
            if (ibegin >= 0)
            {
                while (ibegin >= 0 && ibegin < content.Length)
                {
                    ibegin += 1;
                    int iend = content.IndexOf('>', ibegin);
                    if (iend > ibegin)
                    {
                        string field_name = content.Substring(ibegin, iend - ibegin);
                        if (field_name.EndsWith("/"))//如果是<XXXX/>不用找结束符</XXXX>
                        {
                            field_name = field_name.Substring(0, field_name.Length - 1);
                            XMLMatch("", node_name + (node_name.Length > 0 ? "|" : "") + field_name, dict);
                            ibegin = content.IndexOf('<', iend + 1);
                            continue;
                        }
                        char separator = ' ';
                        int idx = field_name.IndexOf(separator);
                        if (idx > 0)//节点有属性
                        {
                            string paramString = field_name.Substring(idx + 1);
                            field_name = field_name.Substring(0, idx);
                            AddSplitStringValue(paramString, separator, dict, node_name + (node_name.Length > 0 ? "|" : "") + field_name + "|");
                        }
                        string keyword = "</" + field_name + ">";
                        ibegin = iend + 1;
                        iend = content.IndexOf(keyword, ibegin);
                        if (iend >= ibegin)
                        {
                            string content2 = content.Substring(ibegin, iend - ibegin);
                            string keyword2 = "<" + field_name + ">";
                            int idx2 = content2.IndexOf(keyword2);
                            while (idx2 >= 0)//如果有重复的多个<XXXX>
                            {
                                iend = content.IndexOf(keyword, iend + 1);
                                if (iend > ibegin)
                                    content2 = content.Substring(ibegin, iend - ibegin);
                                else
                                    throw new Exception("格式错误");
                                idx2 = content2.IndexOf(keyword2, idx2 + keyword2.Length);
                            }
                            XMLMatch(content2, node_name + (node_name.Length > 0 ? "|" : "") + field_name, dict);
                            ibegin = content.IndexOf('<', iend + keyword.Length);
                        }
                        else
                            throw new Exception("找不到" + field_name + "的结束标志");
                    }
                    else
                        throw new Exception("格式错误");
                }
            }
            else
            {
                string key = node_name;
                int i = 1;
                while (dict.ContainsKey(key))
                {
                    i++;
                    key = node_name + i.ToString();
                }
                dict.Add(key, content.Replace("\\\"", "\""));
            }
        }
        /// <summary>
        /// 分拆参数字符串
        /// </summary>
        /// <param name="paramString">参数</param>
        /// <param name="separator">分隔符</param>
        /// <param name="trim_flag">是否要去掉前后引号</param>
        /// <returns>字符串</returns>
        public static List<string> SplitString(string paramString, char separator, bool trim_flag)
        {
            List<string> values = new List<string>();
            int ibegin = 0;
            bool isbegin = false;
            for (int i = 0; i < paramString.Length; i++)
            {
                bool is_last = (i == paramString.Length - 1);
                char chr = paramString[i];
                if (chr.Equals('\'') || chr.Equals('"')) isbegin = !isbegin;
                if (chr.Equals(separator) && !isbegin)
                {
                    string val = paramString.Substring(ibegin, i - ibegin);
                    if (trim_flag) val = GetSplitString(val);
                    values.Add(val);
                    ibegin = i + 1;
                }
                if (is_last)
                {
                    string val = paramString.Substring(ibegin);
                    if (trim_flag) val = GetSplitString(val);
                    values.Add(val);
                }
            }
            return values;
        }
        private static string GetSplitString(string val)
        {
            string content = val.Trim();
            if (content.StartsWith("'") && content.EndsWith("'"))
                content = content.Substring(1, content.Length - 2).Replace("''", "'");
            if (content.StartsWith("\"") && content.EndsWith("\""))
                content = content.Substring(1, content.Length - 2).Replace("\"\"", "\"");
            return content;
        }
        /// <summary>
        /// 分拆参数字符串
        /// </summary>
        /// <param name="paramString">参数</param>
        /// <param name="separator">分隔符</param>
        /// <returns>字符串</returns>
        public static void AddSplitStringValue(string paramString, char separator, Dictionary<string, string> values, string node_name)
        {
            List<string> str_list = SplitString(paramString, separator, false);
            foreach (string value in str_list)
            {
                if (value == null || value.Length == 0) continue;
                int idx = value.IndexOf('=');
                string key = "";
                string content = "";
                if (idx > 0)
                {
                    content = GetSplitString(value.Substring(idx + 1));
                    key = value.Substring(0, idx).Trim();
                }
                else
                    key = value.Trim();
                key = node_name + key;
                int i = 1;
                while (values.ContainsKey(key))
                {
                    i++;
                    key = node_name + i.ToString();
                }
                values.Add(key, GetSplitString(content.Replace("\\\"", "\"")));
            }
        }
    }
}
